package com.hzit.config;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.hzit.constants.TokenConstants;


import com.hzit.util.JwtUtil;
import com.hzit.util.R;
import io.jsonwebtoken.Claims;
import jdk.nashorn.internal.parser.Token;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

@Component
@Slf4j
public class HzitAuthFilter implements GlobalFilter, Ordered {
	@Autowired
	private StringRedisTemplate redisTemplate;
	@Autowired
	private WhiteListProperties whiteListProperties;

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		ServerHttpRequest request = exchange.getRequest();
		List<String> whiteList = whiteListProperties.getPaths();
		String path = request.getURI().getPath();
		log.info("path:{}",path);
		boolean b = pathMatcher(path,whiteList);
		if(b){
			return chain.filter(exchange);
		}
		String header = request.getHeaders().getFirst(TokenConstants.AUTHENTICATION);

		if(StrUtil.isBlank(header)){
			log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
			return webFluxResponseWriter(exchange,"认证不成功！", HttpStatus.UNAUTHORIZED.value());
		}

		String token = getToken(header);
		Claims claims = JwtUtil.parseToken(token);
		if(claims == null){
			log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
			return webFluxResponseWriter(exchange,"Token信息丢失或无效！", HttpStatus.UNAUTHORIZED.value());
		}

		String uuidToken = (String) claims.get(TokenConstants.JWT_TOKEN);

		String redisKey = getRedisKey(uuidToken);

		if(StrUtil.isBlank(redisKey) || !redisTemplate.hasKey(redisKey)){
			log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
			return webFluxResponseWriter(exchange,"登录信息错误，请稍后重试！", HttpStatus.UNAUTHORIZED.value());
		}
		return chain.filter(exchange);
	}

	private boolean pathMatcher(String path, List<String> whiteList) {
		for (String s : whiteList) {
			return path.contains(s);
		}
		return false;
	}


	private String getRedisKey(String uuidToken) {
		return TokenConstants.REDIS_PREFIX + uuidToken;
	}


	private String getToken(String header) {
		if(header.startsWith("Bearer ")){
			String token = header.replaceAll(TokenConstants.PREFIX, "");
			return token;
		}
		return null;
	}


	private Mono<Void> webFluxResponseWriter(ServerWebExchange exchange, String msg,int code) {
		ServerHttpResponse response = exchange.getResponse();
		R  fail = R.fail(code, msg);
		DataBuffer buffer = response.bufferFactory().wrap(JSON.toJSONString(fail).getBytes());
		return response.writeWith(Mono.just(buffer));
	}

	@Override
	public int getOrder() {
		return 0;
	}
}
